﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Diagnostics;
using MN.Framework.Common;
using MN.Framework.MetaData;


namespace MN.Framework.Common.Service
{
    public class ServiceFactory : MarshalByRefObject
    {
        public static T Create<T>()
        {
            return (T)Activator.CreateInstance<T>();
        }
        public static T Create<T>(string fullTypeName)
        {
            //return (T)Activator.CreateInstance(Type.GetType(FullTypeName));
            return (T)System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(fullTypeName);
        }
        public static T Create<T>(Type entityType)
        {
            return (T)Activator.CreateInstance(entityType);
        }
        public static dynamic Create(Type entityType)
        {
            return Activator.CreateInstance(entityType);
        }

        public static BaseEntity CreateRelatedEntity<T>(string refColumnName) where T : BaseEntity
        {
            var attrs = Attribute.GetCustomAttributes(typeof(T), typeof(AssociatedWithAttribute))
                .Select(at => (AssociatedWithAttribute)at).ToList();
            foreach (var attr in attrs)
            {
                if (attr.ForiengKeyField.Equals(refColumnName, StringComparison.CurrentCultureIgnoreCase))
                {
                    return Create<BaseEntity>(attr.ReferencedEntityType);
                }
            }
            var fkColumn = GetColumns<T>().FirstOrDefault(c => c.Name == refColumnName);
            return Create<BaseEntity>(fkColumn.BaseType);
        }
        public static BaseEntity CreateRelatedEntity(Type entityType, string refColumnName)
        {
            var attrs = Attribute.GetCustomAttributes(entityType, typeof(AssociatedWithAttribute)).Select(at => (AssociatedWithAttribute)at);
            foreach (var attr in attrs)
            {
                if (attr.ForiengKeyField.Equals(refColumnName, StringComparison.CurrentCultureIgnoreCase))
                {
                    return Create<BaseEntity>(attr.ReferencedEntityType);
                }
            }
          return null;
        }
        public static List<ColumnInfo> GetColumns(BaseEntity entity)
        {
            List<ColumnInfo> columns = new List<ColumnInfo>();

            var instance = entity as BaseEntity;

            instance.GetColumns(columns);

            return columns;
        }
        public static List<ColumnInfo> GetColumns<TEntityType>() where TEntityType : BaseEntity
        {

            var instance = ServiceFactory.Create<TEntityType>() as BaseEntity;
            return GetColumns(instance);

        }     
        public static List<ColumnInfo> GirdColumns(BaseEntity entity)
        {
            return GetColumns(entity).Where(x => x.Type != ColumnType.Image).ToList();
        }
        public static List<ColumnInfo> GirdColumns<TEntityType>() where TEntityType : BaseEntity
        {
            return GetColumns<TEntityType>().Where(x => x.Type != ColumnType.Image).ToList();
        }

    }
}
